home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 3
/
Cream of the Crop 3.iso
/
utility
/
move15.zip
/
MOVE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-05
|
23KB
|
997 lines
/*
Auto: sc Move NOLINK NODEBUG OPT NOSTARTUP PARM=REGISTER NOSTACKCHECK DATA=NEAR CODE=NEAR STRINGMERGE
Auto: slink FROM Move.o TO Move LIB LIB:sc.lib LIB:amiga.lib VERBOSE NODEBUG
*/
/* $Revision Header built automatically *************** (do not edit) ************
**
** ⌐ Copyright by GuntherSoft
**
** File : SnakeSYS:CPrgs/Utils/Move.c
** Created on : Wednesday, 11.08.93 15:01:14
** Created by : Kai Iske
** Current revision : V1.5
**
**
** Purpose
** -------
** - Small move utility which supports wildcards and doesn`t use
** Rename() nor Copy() nor anything similar...
**
** Revision V1.5
** --------------
** created on Tuesday, 05.10.93 01:42:53 by Kai Iske. LogMessage :
** -*- changed on Tuesday, 05.10.93 02:03:22 by Kai Iske. LogMessage :
** - Freed the FileInfoBlock _BEFORE_ setting the Bits, Comment
** etc. This lead to MungWall hits (of course it did)
** (Reported by Nico Francois)
** -*- created on Tuesday, 05.10.93 01:42:53 by Kai Iske. LogMessage :
** - Exidentially called one ExAll() without ED_SIZE
** This lead to some calls to DoTheMove without the Size set ;)
** (Reported by Karsten Weiss)
**
** Revision V1.4
** --------------
** created on Friday, 01.10.93 16:55:15 by Kai Iske. LogMessage :
** -*- created on Friday, 01.10.93 16:55:15 by Kai Iske. LogMessage :
** - Now uses Rename() when source and dest are on the same
** device. This is faster ;) Why haven`t I thought of that
** earlier ??? ;)
**
** Revision V1.3
** --------------
** created on Wednesday, 25.08.93 16:32:43 by Kai Iske. LogMessage :
** - UnLock Problem solved when doing recursive Dir-Moves
** This bug lead to "Object in use" error messages
**
** Revision V1.2
** --------------
** created on Tuesday, 17.08.93 22:48:38 by Kai Iske. LogMessage :
** - Added CTRL-C checking
** - Added FORCE Flag in order to move read/deleteprotected or
** to overwrite a delete/writeprotected files
**
** Revision V1.1
** --------------
** created on Monday, 16.08.93 22:53:34 by Kai Iske. LogMessage :
** - Added well known CLONE, DATES, COM, NOPRO,
** QUIET and NOREQ options also used by e.g. Rename
**
** Revision V1.0
** --------------
** created on Wednesday, 11.08.93 15:01:14 by Kai Iske. LogMessage :
** --- Initial release ---
**
*********************************************************************************/
#define REVISION "1.5"
#define REVDATE "05.10.93"
#define REVTIME "02:03:22"
#define AUTHOR "Kai Iske"
#define VERNUM 1
#define REVNUM 5
#include <string.h>
#include <stdlib.h>
#include <exec/types.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <exec/memory.h>
#include <exec/execbase.h>
#include <dos/exall.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
/**********************************************************************/
/* Defines for Flags */
/**********************************************************************/
#define CLONE 0x0001
#define DATES 0x0002
#define NOPRO 0x0004
#define COM 0x0008
#define QUIET 0x0010
#define FORCE 0x0020
#define WATCHSIGS SIGBREAKF_CTRL_C
/**********************************************************************/
/* Static char definitions */
/**********************************************************************/
static char *Version = "$VER: Move "REVISION" ("REVDATE")\0";
static char *Template = "FROM/M,TO/A,CLONE/S,DATES/S,NOPRO/S,COM/S,QUIET/S,NOREQ/S,FORCE/S";
enum {FROM_ARG, TO_ARG, CLONE_ARG, DATES_ARG, NOPRO_ARG, COM_ARG, QUIET_ARG, NOREQ_ARG, FORCE_ARG, LAST_ARG};
/**********************************************************************/
/* Prototypes */
/**********************************************************************/
int __saveds DoMove(void);
BOOL DoTheMove(char *FromFile, char *ToPath, BOOL PatternFrom, BPTR OutHandle, struct DOSBase *DOSBase, LONG Type, ULONG Size, UWORD CopyFlags, LONG *HitMask);
BOOL DoMoveFile(char *FromFile, char *ToPath, char *Buffer, BPTR OutHandle, struct DOSBase *DOSBase, ULONG Size, UWORD CopyFlags, LONG *HitMask);
/**********************************************************************/
/* The main program */
/**********************************************************************/
int __saveds DoMove(void)
{
struct FileInfoBlock *FIB;
struct ExecBase *SysBase = *((struct ExecBase **)0x4L);
struct DOSBase *DOSBase;
struct Process *MyProc = (struct Process *)SysBase->ThisTask;
struct RDArgs *RDArgs;
struct ExAllControl *EAC;
struct ExAllData *EAB, *EAD;
APTR *Args,
*OldWindow;
BPTR DirLock,
OutHandle;
char **FromPtr;
char *ToPtr;
char Pattern[256];
char PathName[256];
char Buffer[256];
LONG HitMask;
UWORD NumFrom = 0, PatternType, CopyFlags = 0;
BOOL PatternFrom, GoOn = TRUE, Scanning;
// Ignore startup from WB
if(!(MyProc->pr_CLI))
{
struct Message *MyMsg;
WaitPort(&MyProc->pr_MsgPort);
MyMsg = GetMsg(&MyProc->pr_MsgPort);
Disable();
ReplyMsg(MyMsg);
return(0);
}
// Do the wild thing
if((DOSBase = (struct DOSBase *)OpenLibrary("dos.library", 37)))
{
if((FIB = AllocVec(sizeof(struct FileInfoBlock), MEMF_CLEAR)))
{
// Get buffer for ReadArgs()
if((Args = AllocVec((LAST_ARG * sizeof(ULONG)), MEMF_CLEAR)))
{
// Get structure for ExAll()
if((EAC = AllocDosObject(DOS_EXALLCONTROL, NULL)))
{
// Get buffer for ExAll()
if((EAB = AllocVec((sizeof(struct ExAllData)*20), MEMF_CLEAR)))
{
// Parse commandline
if((RDArgs = ReadArgs(Template, (ULONG *)Args, NULL)))
{
// From and to really there ??
if(Args[FROM_ARG] && Args[TO_ARG])
{
OutHandle = Output();
// Get Flags
if(Args[CLONE_ARG])
CopyFlags |= CLONE;
if(Args[DATES_ARG])
CopyFlags |= DATES;
if(Args[NOPRO_ARG])
CopyFlags |= NOPRO;
if(Args[COM_ARG])
CopyFlags |= COM;
if(Args[QUIET_ARG])
CopyFlags |= QUIET;
if(Args[FORCE_ARG])
CopyFlags |= FORCE;
// Check for NOREQ Option
if(Args[NOREQ_ARG])
{
OldWindow = MyProc->pr_WindowPtr;
MyProc->pr_WindowPtr = (void *)(-1L);
}
// Get pointers to Files
FromPtr = (char **)Args[FROM_ARG];
ToPtr = (char *)Args[TO_ARG];
// Count FROM entries
while(*FromPtr++)
NumFrom++;
// Restore FromPtr
FromPtr = (char **)Args[FROM_ARG];
// Set pattern if there are more than 1
// FROM files or if the only FROM file
// is a pattern
if(NumFrom > 1)
PatternFrom = TRUE;
else
PatternFrom = ParsePatternNoCase(*FromPtr, Pattern, 256);
// If a pattern is used, check
// whether the dest really is a dir
if(PatternFrom)
{
// Try to obtain a lock
if((DirLock = Lock(ToPtr, ACCESS_READ)))
{
// Check file
if(Examine(DirLock, FIB))
{
// Get type of destination entry
GoOn = (FIB->fib_DirEntryType > 0);
// If it`s not a directory (multiple files are to be moved)
// issue an error
if(!GoOn)
FPuts(OutHandle, "\nMove : Multiple files may not be moved to a single file\n");
}
else
{
// Examine() failed -> Abort
GoOn = FALSE;
PrintFault(IoErr(), "\nMove ");
}
// Unlock CheckDir
UnLock(DirLock);
}
else
{
// If lock failed issue an error
PrintFault(IoErr(), "\nMove ");
GoOn = FALSE;
}
}
// Loop for all source files
while(NumFrom && GoOn)
{
// Check for CTRL-C
if(GoOn)
HitMask = CheckSignal(WATCHSIGS);
if(!HitMask && GoOn)
{
// Check if this source is a pattern
strcpy(Buffer, FilePart(*FromPtr));
strupr(Buffer);
PatternType = ParsePatternNoCase(Buffer, Pattern, 256);
// It is a pattern
if(PatternType == 1)
{
// Create name of source
strcpy(Buffer, *FromPtr);
*PathPart(Buffer) = '\0';
// Get Lock for Source - Directory
if((DirLock = Lock(Buffer, ACCESS_READ)))
{
// Setup ExAllControl-Structure
EAC->eac_LastKey = 0L;
EAC->eac_MatchString = Pattern;
EAC->eac_MatchFunc = NULL;
do
{
// Check for CTRL-C
if(GoOn)
HitMask = CheckSignal(WATCHSIGS);
if(HitMask)
GoOn = FALSE;
// Scan directory
Scanning = ExAll(DirLock, EAB, (20*sizeof(struct ExAllData)), ED_SIZE, EAC);
// Issue Error
if(GoOn && (!Scanning) && (IoErr() != ERROR_NO_MORE_ENTRIES))
{
PrintFault(IoErr(), "\nMove ");
GoOn = FALSE;
}
// End of Dir reached
if(EAC->eac_Entries == 0)
Scanning = FALSE;
else if(GoOn)
{
EAD = EAB;
do
{
// Check for CTRL-C
if(GoOn)
HitMask = CheckSignal(WATCHSIGS);
if(!HitMask && GoOn)
{
// Createfilename for this file to be moved
strcpy(PathName, *FromPtr);
*PathPart(PathName) = '\0';
AddPart(PathName, EAD->ed_Name, 256);
// Move file
if((GoOn = DoTheMove(PathName, ToPtr, TRUE, OutHandle, DOSBase, EAD->ed_Type, EAD->ed_Size, CopyFlags, &HitMask)) && (EAD->ed_Type > 0))
{
// Delete directory after a succesful move
if(!(GoOn = DeleteFile(PathName)))
PrintFault(IoErr(), "\nMove ");
}
EAD = EAD->ed_Next;
}
else
GoOn = FALSE;
} while(EAD && GoOn);
}
} while(Scanning);
// Unlock source directory
UnLock(DirLock);
}
else
{
// Issue error, if dir could not be locked
PrintFault(IoErr(), "\nMove ");
GoOn = FALSE;
}
}
// No pattern
else if(PatternType == 0)
{
// Try to lock source file/dir
if((DirLock = Lock(*FromPtr, ACCESS_READ)))
{
// Examine this lock
if(Examine(DirLock, FIB))
{
// Unlock directory and do the move
UnLock(DirLock);
if((GoOn = DoTheMove(*FromPtr, ToPtr, TRUE, OutHandle, DOSBase, FIB->fib_DirEntryType, FIB->fib_Size, CopyFlags, &HitMask)) && (FIB->fib_DirEntryType > 0))
{
// Delete dir after a succesfull move
if(!(GoOn = DeleteFile(*FromPtr)))
PrintFault(IoErr(), "\nMove ");
}
}
else
{
// Issue error on failed Examine()
PrintFault(IoErr(), "\nMove ");
GoOn = FALSE;
UnLock(DirLock);
}
}
else
{
// No Lock() no more moves
PrintFault(IoErr(), "\nMove ");
GoOn = FALSE;
}
}
// Error condition
else
{
PrintFault(IoErr(), "\nMove ");
GoOn = FALSE;
}
NumFrom--;
FromPtr++;
}
else
GoOn = FALSE;
}
}
// Free ReadArgs
FreeArgs(RDArgs);
}
else
PrintFault(IoErr(), "\nMove ");
// Free ExAll-Buffer
FreeVec(EAB);
}
else
PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
// Free ExAllControl Structure
FreeDosObject(DOS_EXALLCONTROL, (void *)EAC);
}
else
PrintFault(IoErr(), "\nMove ");
// Free Argument Buffer
FreeVec(Args);
}
else
PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
FreeVec(FIB);
}
else
PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
// Check for Abort-Signals
if(HitMask && !(CopyFlags & QUIET))
{
// Display appropriate message
if(HitMask & SIGBREAKF_CTRL_C)
FPuts(OutHandle, "\nMove ^C...\n");
}
// Close DOSLibrary
CloseLibrary((struct Library *)DOSBase);
}
// Restore old window pointer (if any)
if(OldWindow)
MyProc->pr_WindowPtr = OldWindow;
// Depending on this flag return appropriate return code
if(GoOn)
return(0);
else
return(10);
}
/**********************************************************************/
/* Do the move */
/**********************************************************************/
BOOL DoTheMove(char *FromFile, char *ToPath, BOOL PatternFrom, BPTR OutHandle, struct DOSBase *DOSBase, LONG Type, ULONG Size, UWORD CopyFlags, LONG *HitMask)
{
struct ExAllControl *EAC;
struct ExAllData *EAB, *EAD;
char NewDir[256];
char Buffer[256];
UWORD Len;
BPTR DirLock;
BOOL RetVal = TRUE, Scanning;
// If a pattern is used print the name of the file to be moved
if(PatternFrom && !(CopyFlags & QUIET))
{
strcpy(Buffer, FromFile);
strcat(Buffer, "...");
Write(OutHandle, " ", 1);
Write(OutHandle, Buffer, strlen(Buffer));
}
// Is it a directory ???
// If yes, recursively loop for all entries within dir
if(Type > 0)
{
strcpy(Buffer, FromFile);
// Get length of from name
Len = strlen(Buffer);
if(Len)
{
if(Buffer[Len - 1] == '/')
Buffer[Len - 1] = '\0';
// Copy dest name to buffer
strcpy(NewDir, ToPath);
// Add name of from directory
AddPart(NewDir, FilePart(Buffer), 256);
// Try to lock directory or
// create it, if not existent
if(!(DirLock = Lock(NewDir, ACCESS_READ)))
{
if((DirLock = CreateDir(NewDir)) && PatternFrom && !(CopyFlags & QUIET))
Write(OutHandle, " [created]...", 13);
}
// Got the destination directory ???
if(DirLock)
{
// Unlock Directory
UnLock(DirLock);
// Lock sourcedirectory
if((DirLock = Lock(Buffer, ACCESS_READ)))
{
// Get ExAll Control for recursive directory search
if((EAC = AllocDosObject(DOS_EXALLCONTROL, NULL)))
{
// Allocate buffer for move
if((EAB = AllocVec((20*sizeof(struct ExAllData)), MEMF_CLEAR)))
{
EAC->eac_LastKey = 0L;
EAC->eac_MatchString = NULL;
EAC->eac_MatchFunc = NULL;
do
{
// Check for CTRL-C
if(RetVal)
(*HitMask) = CheckSignal(WATCHSIGS);
if((*HitMask))
RetVal = FALSE;
// Scan directory for entries
Scanning = ExAll(DirLock, EAB, (20*sizeof(struct ExAllData)), ED_SIZE, EAC);
// Check for an error
if(RetVal && (!Scanning) && (IoErr() != ERROR_NO_MORE_ENTRIES))
{
PrintFault(IoErr(), "\nMove ");
RetVal = FALSE;
}
// End of Dir reached
if(EAC->eac_Entries == 0)
Scanning = FALSE;
else if(RetVal)
{
EAD = EAB;
do
{
// Check for CTRL-C
if(RetVal)
(*HitMask) = CheckSignal(WATCHSIGS);
if(!(*HitMask) && RetVal)
{
// Create filename of source
strcpy(Buffer, FromFile);
AddPart(Buffer, EAD->ed_Name, 256);
// And start recursion
if((RetVal = DoTheMove(Buffer, NewDir, FALSE, OutHandle, DOSBase, EAD->ed_Type, EAD->ed_Size, CopyFlags, HitMask)) && (EAD->ed_Type > 0))
{
// if file moved was a dir, delete it
if(!(RetVal = DeleteFile(Buffer)))
PrintFault(IoErr(), "\nMove ");
}
// Loop for all entries
EAD = EAD->ed_Next;
}
else
RetVal = FALSE;
} while(EAD && RetVal);
}
} while(Scanning);
// Free ExAll Buffer
FreeVec(EAB);
}
else
{
PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
RetVal = FALSE;
}
// Free ExAllControl Structure
FreeDosObject(DOS_EXALLCONTROL, EAC);
}
else
{
PrintFault(IoErr(), "\nMove ");
RetVal = FALSE;
}
UnLock(DirLock);
}
else
{
PrintFault(IoErr(), "\nMove ");
RetVal = FALSE;
}
}
else
{
PrintFault(IoErr(), "\nMove ");
RetVal = FALSE;
}
}
}
else
{
// On a plain file -> Simply move it
RetVal = DoMoveFile(FromFile, ToPath, Buffer, OutHandle, DOSBase, Size, CopyFlags, HitMask);
}
// If there was a pattern (or a single directory)
// end the Move string
if(PatternFrom && RetVal && !(CopyFlags & QUIET))
FPuts(OutHandle, " moved\n");
// Return Code
return(RetVal);
}
/**********************************************************************/
/* Ein File wirklich moven */
/**********************************************************************/
BOOL DoMoveFile(char *FromFile, char *ToPath, char *Buffer, BPTR OutHandle, struct DOSBase *DOSBase, ULONG Size, UWORD CopyFlags, LONG *HitMask)
{
struct FileInfoBlock *FIB;
struct DevProc *FromDev, *ToDev;
BPTR InFile, OutFile;
APTR CopyBuffer;
char DestName[256];
LONG AvailSize, ReadSize;
BOOL RetVal = TRUE, ErrCpy = FALSE, LoopCpy = TRUE, DoRename = FALSE, RemoveFirst = FALSE;
if((FIB = AllocVec(sizeof(struct FileInfoBlock), MEMF_CLEAR)))
{
strcpy(DestName, ToPath);
// Check, if destfile already exists
// If so, check if it`s a dir.
// Yes -> Copy with sourcename
// No -> Copy with given name
if((OutFile = Lock(DestName, ACCESS_READ)))
{
if(Examine(OutFile, FIB))
{
// If dest is a directory move with source name
if(FIB->fib_DirEntryType > 0)
AddPart(DestName, FilePart(FromFile), 256);
else
RemoveFirst = TRUE;
}
else
{
// No examine -> Use source filename
AddPart(DestName, FilePart(FromFile), 256);
}
UnLock(OutFile);
}
// Try to lock input file
if((InFile = Lock(FromFile, ACCESS_READ)))
{
// Get old protection bits, comment and filedate
if(Examine(InFile, FIB))
{
// In Force mode -> Force read and delete permissons
// for input file
if(CopyFlags & FORCE)
SetProtection(FromFile, ~(FIBF_OTR_READ|FIBF_OTR_DELETE|FIBF_READ|FIBF_DELETE));
}
else
{
PrintFault(IoErr(), "\nMove ");
RetVal = FALSE;
}
// If so, unlock
UnLock(InFile);
}
else
{
PrintFault(IoErr(), "\nMove ");
RetVal = FALSE;
}
// Check whether to use a Rename() or a real Copy-Mode
FromDev = GetDeviceProc(FromFile, NULL);
ToDev = GetDeviceProc(DestName, NULL);
// If the same device is used -> Do the rename
if(FromDev && ToDev && (FromDev->dvp_Port == ToDev->dvp_Port))
DoRename = TRUE;
if(FromDev)
FreeDeviceProc(FromDev);
if(ToDev)
FreeDeviceProc(ToDev);
// No Rename -> Do the right move ;)
if(!DoRename)
{
// Open Input file
if(RetVal && (InFile = Open(FromFile, MODE_OLDFILE)))
{
// Outfile already there ??? and in force mode ???
if((CopyFlags & FORCE) && ((OutFile = Lock(DestName, ACCESS_READ))))
{
// Force delete and write permissons
UnLock(OutFile);
SetProtection(DestName, ~(FIBF_OTR_WRITE|FIBF_OTR_DELETE|FIBF_WRITE|FIBF_DELETE));
}
// Open Output file
if((OutFile = Open(DestName, MODE_NEWFILE)))
{
// Get available size of memory
AvailSize = AvailMem(MEMF_LARGEST);
Size = (Size > AvailSize) ? AvailSize : Size;
// Loop till we get a buffer
while(Size && !(CopyBuffer = AllocVec(Size, MEMF_CLEAR)))
Size -= 1024;
if(CopyBuffer)
{
// Loop for portions of the source file
while(RetVal && LoopCpy)
{
// Check for CTRL-C
if(RetVal)
(*HitMask) = CheckSignal(WATCHSIGS);
if(!(*HitMask) && RetVal)
{
// Read part of file
if((ReadSize = Read(InFile, CopyBuffer, Size)) > 0)
{
// And write it back
if(Write(OutFile, CopyBuffer, ReadSize) == -1)
{
PrintFault(IoErr(), "\nMove ");
RetVal = FALSE;
ErrCpy = TRUE;
}
}
else
{
// EOF ??? -> End copy
if(ReadSize == 0)
LoopCpy = FALSE;
else
{
// Otherwise issue error
PrintFault(IoErr(), "\nMove ");
RetVal = FALSE;
ErrCpy = TRUE;
}
}
}
else
RetVal = FALSE;
}
// Free Copy buffer
FreeVec(CopyBuffer);
}
else
{
// Issue error
PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
RetVal = FALSE;
ErrCpy = TRUE;
}
// Close outfile
Close(OutFile);
}
else
{
// Issue error
PrintFault(IoErr(), "\nMove ");
RetVal = FALSE;
}
// Close InFile
Close(InFile);
}
else
{
// Issue error
PrintFault(IoErr(), "\nMove ");
RetVal = FALSE;
}
}
else
{
// If RemoveFirst is not set, check again ;)
if(!RemoveFirst)
{
if((OutFile = Lock(DestName, ACCESS_READ)))
{
if(Examine(OutFile, FIB))
{
// If dest is a file, delete first
if(FIB->fib_DirEntryType < 0)
RemoveFirst = TRUE;
}
UnLock(OutFile);
}
}
// In Rename() mode, the destination has to be removed first
if(RemoveFirst)
{
// If dest file is protected check for FORCE flag
if(CopyFlags & FORCE)
SetProtection(DestName, ~(FIBF_OTR_WRITE|FIBF_OTR_DELETE|FIBF_WRITE|FIBF_DELETE));
if(!DeleteFile(DestName))
{
PrintFault(IoErr(), "\nMove ");
RetVal = FALSE;
}
}
if(RetVal)
{
// Now try to "rename" the file
if(!Rename(FromFile, DestName))
{
PrintFault(IoErr(), "\nMove ");
RetVal = FALSE;
}
}
}
// Error while copying ?? -> Remove Dest file
if(ErrCpy)
DeleteFile(DestName);
// No Error -> Remove Source file
if(RetVal && !ErrCpy)
{
if(!DoRename && !(RetVal = DeleteFile(FromFile)))
PrintFault(IoErr(), "\nMove ");
else
{
// Set bits etc. as requested
if((CopyFlags & CLONE) || (CopyFlags & DATES))
SetFileDate(DestName, &FIB->fib_Date);
if((CopyFlags & CLONE) || (CopyFlags & COM))
SetComment(DestName, FIB->fib_Comment);
if(((CopyFlags & CLONE) && !(CopyFlags & NOPRO)) || (!(CopyFlags & CLONE) && !(CopyFlags & NOPRO)))
SetProtection(DestName, FIB->fib_Protection);
}
}
// Free FileInfo Block
FreeVec(FIB);
}
else
{
PrintFault(ERROR_NO_FREE_STORE, "\nMove ");
RetVal = FALSE;
}
return(RetVal);
}